"""
--------------------------------------------------------
@File             : EdgeGateCommuChannel.py
@Creat Time       : 2021-01-21
@Author           : wangzp
@Site             :
@Software         : PyCharm
@file Conent      :
--------------------------------------------------------
@Revise history   :
@Version          : V12
@Amendant records :
     1)wangzp  2021-01-21
"""
import json
import EdgeGateData
import socket
from EdgeGateDissymMsgResv import *
from EdgeGateDissymMsgSend import *
import time
import threading
from EdgeGateLog import *


# 发起客户端的任务
def CommuChannelClientTaskFunction():

    # 初始化所有的simdtu连接状态为0
    for item in EdgeGateData.gSimDtuList:
        ip = item['socketIp']
        port = item['socketPort']
        EdgeGateData.gConnectedStateDictionary[(ip, port)] = 0
    while True:
        time.sleep(3)
        # 遍历配置文件协议网关中的json对象，即遍历所有的simdtu
        for item in EdgeGateData.gSimDtuList:
            socketMod = item['socketMod']
            # 判断是否为客户端模式的连接，不是则略过
            if(socketMod!="CLIENT"):
                continue
            id = item['id']
            ip = item['socketIp']
            port = item['socketPort']
            # 判断是否连接，若以连接则略过，未连接则继续尝试连接
            if EdgeGateData.gConnectedStateDictionary[(ip, port)] == 1:
                continue
            try:
                # 客户端模式下通过id来索引socket对象
                EdgeGateData.gClientSocketDictionary[id] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                # 打印状态
                print("客户端线程：尝试对{0}建立连接".format((ip, port)))
                # 尝试 connnet 建立连接
                EdgeGateData.gClientSocketDictionary[id].connect((ip, port))
                # 连接成功后设置该状态为1，通过（ip和端口号）的元组来字典索引
                EdgeGateData.gConnectedStateDictionary[(ip, port)] = 1
                # 打印连接成功，并输出当前连接数量
                print("客户端线程：{0}连接成功，目前共有{1}连接成功".format((ip, port),
                                                   EdgeGateData.getConnectedSuccessCurrentNum()))
                # 启动发送线程
                th_send = threading.Thread(target=MsgSend, args=(
                    1, EdgeGateData.gClientSocketDictionary[id],
                    (ip, port)))
                th_send.start()
                # 启动接受线程
                th_accept = threading.Thread(target=MsgResv, args=(
                    1, EdgeGateData.gClientSocketDictionary[id],
                    (ip, port)))
                th_accept.start()
            except Exception as e:
                print("客户端线程：出现例外！" + str(e))
                # 将该连接状态设置为断开（0）
                EdgeGateData.gConnectedStateDictionary[(ip, port)] = 0
                continue


# 发起服务端的任务
def CommuChannelServerTaskFunction():
    EdgeGateData.gServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    EdgeGateData.gServerSocket.bind(("127.0.0.1", 8888))
    EdgeGateData.gServerSocket.listen(10)
    i = 0
    while True:
        try:
            print("服务端线程：等待对方连接中")
            # 服务端等待接收:accept()
            AcceptSocketTuple = EdgeGateData.gServerSocket.accept()
            # 接收成功后
            # 获取该服务端接收的ip地址
            acceptIP = AcceptSocketTuple[1][0]
            print("服务端线程：接收到ip为{0}".format(acceptIP))
            # 有了该ip，我们就可以获取其是何种设备类型，并将其放入指定的列表中


            # 添加到全局变量，字典存储，通过（IP，端口号）来索引该socket对象（因为ip惟一，后续可以直接改为通过ip索引）
            EdgeGateData.gServerAcceptSocketDictionary[AcceptSocketTuple[1]] = AcceptSocketTuple[0]
            # 设置该连接的连接状态等于1，字典存储，通过（IP，端口号）来索引该状态
            EdgeGateData.gConnectedStateDictionary[AcceptSocketTuple[1]] = 1
            # 添加该accpet到socket元组
            EdgeGateData.gServerAcceptSocketTupleList.append(AcceptSocketTuple)
            print("服务端线程：连接成功,欢迎({0})连接我，目前共有{1}处连接".format(AcceptSocketTuple[1], EdgeGateData.getConnectedSuccessCurrentNum()))

            # 启动发送线程
            th_send = threading.Thread(target=MsgSend,
                                       args=(1, AcceptSocketTuple[0], AcceptSocketTuple[1]))
            th_send.start()
            # 启动接收线程
            th_accept = threading.Thread(target=MsgResv,
                                         args=(1, AcceptSocketTuple[0], AcceptSocketTuple[1]))
            th_accept.start()
        except Exception as e:
            print("服务端线程：未连接" + str(e))
            # 设置连接状态为0
            EdgeGateData.gConnectedStateDictionary[AcceptSocketTuple[1]] = 0
            # 关闭socket
            EdgeGateData.gServerAcceptSocketDictionary[AcceptSocketTuple[1]].close()
            AcceptSocketTuple[0].close()
            continue
            pass


# 初始化任务，读取配置文件
def SystemInitTask():
    # 读取simdtu json配置文件内容,返回字典格式
    print("初始化任务：读取JSON配置文件")
    EdgeGateData.gSimDtuList = eval(open('./netGateway.json').read())
    print(EdgeGateData.gSimDtuList)





if __name__ == '__main__':

    # 初始化读取配置文件（包含上游和下游的设备）
    SystemInitTask()

    # 启动客户端状态，以主动连接上游设备
    # 负责与云端物联网网元设备通信，这类设备支持socket通信，EG以客户端的方式和云端网元建立socket链接。
    CommuChannelClient = threading.Thread(target=CommuChannelClientTaskFunction)
    CommuChannelClient.start()
    # 启动服务端状态，等待dtu连接
    # 负责与下游Dtu的socket通信，Dtu负责传感器接入，此处socket主要用户和下游DTU通信；
    # 负责与要接入的网络传感器设备通信，这类传感器自身就支持socket通信，EG建立服务器端socket，接纳各种配置到该服务器的网络设备建立接入链接；
    CommuChannelServerTask = threading.Thread(target=CommuChannelServerTaskFunction)
    CommuChannelServerTask.start()
